﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using FluentUnity;
using FluentUnity.Conventions;

// ReSharper disable CheckNamespace
namespace Microsoft.Practices.Unity
// ReSharper restore CheckNamespace
{
    public static class ContainerExtensions
    {
        /// <summary>
        /// Allows customization of the conventions before applying them to the provided <paramref name="container"/>
        /// </summary>
        /// <param name="container">The container to apply the conventions to.</param>
        /// <param name="conventions">The conventions to use.</param>
        public static void UniteFluently(this IUnityContainer container, Action<UnityConvention> conventions)
        {
            Ensure.IsNotNull(() => container);
            Ensure.IsNotNull(() => conventions);

            var convention = new UnityConvention();
            conventions(convention);
            convention.ApplyTo(container);
        }

        /// <summary>
        /// Performs a default convention-based registration for the provided assemblies
        /// </summary>
        /// <param name="container">The container to apply the conventions to.</param>
        /// <param name="assemblies">The assemblies to use.</param>
        public static void UniteFluently(this IUnityContainer container, params Assembly[] assemblies)
        {
            container.UniteFluently(c => c.AddAssemblies(assemblies));
        }

        /// <summary>
        /// Helper extension method to Log FluentUnity messages directly to the console
        /// </summary>
        /// <param name="convention">The convention.</param>
        public static void LogToConsole(this UnityConvention convention)
        {
            convention.Log += Console.WriteLine;
        }

        /// <summary>
        /// Concatenates all instances in <paramref name="target"/> using the specified <paramref name="formatter"/> and <paramref name="separator"/>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="target">The target.</param>
        /// <param name="formatter">The formatter.</param>
        /// <param name="separator">The separator.</param>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public static string ToString<T>(this IEnumerable<T> target, Func<T, object> formatter, string separator = ", ")
        {
            var sb = new StringBuilder();
            if (target != null)
            {
                foreach (T item in target)
                {
                    if (sb.Length > 0)
                        sb.Append(separator);

                    if (formatter != null)
                        sb.Append(formatter(item));
                    else
                        sb.Append((item == null) ? "[null]" : item.ToString());
                }
            }
            return sb.ToString();
        }
    }
}
